
package com.hlkj.pay.service.merchant.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.hlkj.framework.mybatis.core.query.QueryWrapperX;
import com.hlkj.framework.mybatis.core.utils.MyBatisUtils;
import com.hlkj.pay.dto.merchant.report.MerchantReportDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportInfoPageDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportInfoPageQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.mapper.merchant.*;
import com.hlkj.pay.infrastructure.model.merchant.*;
import com.hlkj.pay.service.CommonSnFilterService;
import com.hlkj.pay.service.merchant.IMerchantReportService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/12/20 13:16
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class MerchantReportServiceImpl extends CommonSnFilterService implements IMerchantReportService {

    private final MerchantReportInfoMapper merchantReportInfoMapper;

    private final MerchantCertInfoMapper merchantCertInfoMapper;

    private final MerchantLicenseMapper merchantLicenseMapper;

    private final MerchantCardMapper merchantCardMapper;

    private final MerchantReportBusinessMapper merchantReportBusinessMapper;

    private final MerchantReportAmountMapper merchantReportAmountMapper;


    @Override
    public PageResult<MerchantReportInfoPageDto> queryPage(MerchantReportInfoPageQueryDto merchantReportInfoPageQueryDto) {
        if (!StringUtils.hasText(merchantReportInfoPageQueryDto.getSortingFields())) {
            merchantReportInfoPageQueryDto.setSortingFields("a.id");
        }
        IPage<MerchantReportInfoPageDto> mpPage = MyBatisUtils.buildPage(merchantReportInfoPageQueryDto);
        QueryWrapper<MerchantReportInfoDO> queryWrapper = buildInfoWrapper(merchantReportInfoPageQueryDto);
        // queryWrapper.orderByDesc("a.id");
        merchantReportInfoMapper.selectMerchantReportPage(mpPage, queryWrapper);
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public Long saveReport(MerchantReportDto merchantReportDto) {
        // 主表
        MerchantReportInfoDO merchantReportInfoDO = merchantReportDto.getMerchantReportInfo();
        merchantReportInfoMapper.insert(merchantReportInfoDO);
        // 报备营业执照信息
        MerchantLicenseDO merchantReportLicenseDO = merchantReportDto.getMerchantReportLicense();
        // 报备法人信息
        MerchantCertInfoDO merchantReportLegalDO = merchantReportDto.getMerchantReportLegal();
        // 联系人信息
        MerchantCertInfoDO merchantReportContactDO = merchantReportDto.getMerchantReportContact();
        // 实际控制人
        MerchantCertInfoDO merchantReportControllerDO = merchantReportDto.getMerchantReportController();
        // 报备受益人信息
        List<MerchantCertInfoDO> merchantReportBenefits = merchantReportDto.getMerchantReportBenefitList();
        // 企业控股股东信息
        List<MerchantCertInfoDO> merchantReportShareholdersList = merchantReportDto.getMerchantReportShareholderList();
        // 经营信息
        MerchantReportBusinessDO merchantReportBusinessDO = merchantReportDto.getMerchantReportBusiness();
        // 报备结算卡信息
        MerchantCardDO merchantReportCardDO = merchantReportDto.getMerchantReportCard();
        if (merchantReportLicenseDO != null) {
            merchantReportLicenseDO.setRelationId(merchantReportInfoDO.getId());
            merchantReportLicenseDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
            merchantReportLicenseDO.setSn(merchantReportInfoDO.getSn());
            merchantReportLicenseDO.setChannelCode(merchantReportInfoDO.getChannelCode());
        }
        if (merchantReportBusinessDO != null) {
            merchantReportBusinessDO.setReportId(merchantReportInfoDO.getId());
            merchantReportBusinessDO.setSn(merchantReportInfoDO.getSn());
        }
        if (merchantReportCardDO != null) {
            merchantReportCardDO.setRelationId(merchantReportInfoDO.getId());
            merchantReportCardDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
            merchantReportCardDO.setSn(merchantReportInfoDO.getSn());
        }
        List<MerchantCertInfoDO> merchantReportCertInfoList = new ArrayList<>();
        if (merchantReportLegalDO != null) {
            merchantReportLegalDO.setType(MerchantEnum.CERT_INFO_TYPE.LEGAL.getCode());
            merchantReportLegalDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
            merchantReportCertInfoList.add(merchantReportLegalDO);
        }
        if (merchantReportContactDO != null) {
            merchantReportContactDO.setType(MerchantEnum.CERT_INFO_TYPE.CONTACT.getCode());
            merchantReportContactDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
            merchantReportCertInfoList.add(merchantReportContactDO);
        }
        if (merchantReportControllerDO != null) {
            merchantReportControllerDO.setType(MerchantEnum.CERT_INFO_TYPE.CONTROLLER.getCode());
            merchantReportControllerDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
            merchantReportCertInfoList.add(merchantReportControllerDO);
        }
        if (merchantReportBenefits != null) {
            merchantReportBenefits.stream().forEach(merchantReportCertInfoDO -> {
                merchantReportControllerDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
                merchantReportCertInfoDO.setType(MerchantEnum.CERT_INFO_TYPE.BENEFIT.getCode());
            });
            merchantReportCertInfoList.addAll(merchantReportBenefits);
        }
        if (merchantReportShareholdersList != null) {
            merchantReportShareholdersList.stream().forEach(merchantReportCertInfoDO -> {
                merchantReportControllerDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
                merchantReportCertInfoDO.setType(MerchantEnum.CERT_INFO_TYPE.SHAREHOLDER.getCode());
            });
            merchantReportCertInfoList.addAll(merchantReportShareholdersList);
        }
        if (CollectionUtils.isNotEmpty(merchantReportCertInfoList)) {
            merchantReportCertInfoList.stream().forEach(merchantReportBenefitDO -> {
                merchantReportBenefitDO.setRelationId(merchantReportInfoDO.getId());
                merchantReportBenefitDO.setRelationType(MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode());
                merchantReportBenefitDO.setSn(merchantReportInfoDO.getSn());
            });
        }
        if (merchantReportLicenseDO != null) {
            merchantLicenseMapper.insert(merchantReportLicenseDO);
        }
        merchantCardMapper.insert(merchantReportCardDO);
        if (CollectionUtils.isNotEmpty(merchantReportCertInfoList)) {
            merchantCertInfoMapper.insertBatch(merchantReportCertInfoList);
        }
        merchantReportBusinessMapper.insert(merchantReportBusinessDO);
        return merchantReportInfoDO.getId();
    }

    @Override
    public MerchantReportInfoDO detail(Long id) {
        return merchantReportInfoMapper.selectById(id);
    }

    @Override
    public Long updateReport(MerchantReportDto merchantReportDto) {
        // 主表
        MerchantReportInfoDO merchantReportInfoDO = merchantReportDto.getMerchantReportInfo();
        merchantReportInfoMapper.updateById(merchantReportInfoDO);
        // 进件营业执照信息
        MerchantLicenseDO merchantReportLicenseDO = merchantReportDto.getMerchantReportLicense();
        // 进件法人信息
        MerchantCertInfoDO merchantReportLegalDO = merchantReportDto.getMerchantReportLegal();
        // 联系人信息
        MerchantCertInfoDO merchantReportContactDO = merchantReportDto.getMerchantReportContact();
        // 实际控制人
        MerchantCertInfoDO merchantReportControllerDO = merchantReportDto.getMerchantReportController();
        // 进件受益人信息
        List<MerchantCertInfoDO> merchantReportBenefits = merchantReportDto.getMerchantReportBenefitList();
        // 企业控股股东信息
        List<MerchantCertInfoDO> merchantReportShareholdersList = merchantReportDto.getMerchantReportShareholderList();
        // 经营信息
        MerchantReportBusinessDO merchantReportBusinessDO = merchantReportDto.getMerchantReportBusiness();
        // 进件结算卡信息
        MerchantCardDO merchantReportCardDO = merchantReportDto.getMerchantReportCard();
        Integer relationType = MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode();
        if (merchantReportLicenseDO != null) {
            merchantReportLicenseDO.setRelationId(merchantReportInfoDO.getId());
            merchantReportLicenseDO.setRelationType(relationType);
            merchantReportLicenseDO.setSn(merchantReportInfoDO.getSn());
            merchantReportLicenseDO.setChannelCode(merchantReportInfoDO.getChannelCode());
        }
        if (merchantReportBusinessDO != null) {
            merchantReportBusinessDO.setReportId(merchantReportInfoDO.getId());
            merchantReportBusinessDO.setSn(merchantReportInfoDO.getSn());
        }
        if (merchantReportCardDO != null) {
            merchantReportCardDO.setRelationId(merchantReportInfoDO.getId());
            merchantReportCardDO.setRelationType(relationType);
            merchantReportCardDO.setSn(merchantReportInfoDO.getSn());
        }
        List<MerchantCertInfoDO> merchantReportCertInfoList = new ArrayList<>();
        if (merchantReportLegalDO != null) {
            merchantReportLegalDO.setType(MerchantEnum.CERT_INFO_TYPE.LEGAL.getCode());
            merchantReportLegalDO.setRelationType(relationType);
            merchantReportCertInfoList.add(merchantReportLegalDO);
        }
        if (merchantReportContactDO != null) {
            merchantReportContactDO.setType(MerchantEnum.CERT_INFO_TYPE.CONTACT.getCode());
            merchantReportContactDO.setRelationType(relationType);
            merchantReportCertInfoList.add(merchantReportContactDO);
        }
        if (merchantReportControllerDO != null) {
            merchantReportControllerDO.setType(MerchantEnum.CERT_INFO_TYPE.CONTROLLER.getCode());
            merchantReportControllerDO.setRelationType(relationType);
            merchantReportCertInfoList.add(merchantReportControllerDO);
        }
        if (merchantReportBenefits != null) {
            merchantReportBenefits.stream().forEach(benefit -> {
                benefit.setType(MerchantEnum.CERT_INFO_TYPE.BENEFIT.getCode());
                benefit.setRelationType(relationType);
            });
            merchantReportCertInfoList.addAll(merchantReportBenefits);
        }
        if (merchantReportShareholdersList != null) {
            merchantReportShareholdersList.stream().forEach(shareholder -> {
                shareholder.setType(MerchantEnum.CERT_INFO_TYPE.SHAREHOLDER.getCode());
                shareholder.setRelationType(relationType);
            });
            merchantReportCertInfoList.addAll(merchantReportShareholdersList);
        }
        if (CollectionUtils.isNotEmpty(merchantReportCertInfoList)) {
            merchantReportCertInfoList.stream().forEach(merchantReportCertInfoDO -> {
                merchantReportCertInfoDO.setRelationId(merchantReportInfoDO.getId());
                merchantReportCertInfoDO.setRelationType(relationType);
                merchantReportCertInfoDO.setSn(merchantReportInfoDO.getSn());
            });
        }
        if(merchantReportLicenseDO!=null){
            merchantLicenseMapper.update(merchantReportLicenseDO, buildLicenseWrapper(merchantReportInfoDO.getId(), relationType));
        }
        merchantCardMapper.update(merchantReportCardDO, buildCardWrapper(merchantReportInfoDO.getId(), relationType));
        if (CollectionUtils.isNotEmpty(merchantReportCertInfoList)) {
            // 证件信息 先删 再加
            merchantCertInfoMapper.delete(buildCertInfoWrapper(merchantReportInfoDO.getId(), relationType));
            merchantCertInfoMapper.insertBatch(merchantReportCertInfoList);
        }
        merchantReportBusinessMapper.update(merchantReportBusinessDO, buildBusinessWrapper(merchantReportInfoDO.getId()));
        return merchantReportInfoDO.getId();
    }

    @Override
    public MerchantReportDto domainDetail(Long id) {
        MerchantReportInfoDO merchantReportInfoDO = merchantReportInfoMapper.selectById(id);
        if (merchantReportInfoDO == null) {
            return null;
        }
        Integer relationType = MerchantEnum.MERCHANT_COMMON_RELATION_TYPE.REPORT.getCode();
        List<MerchantCertInfoDO> merchantAccessCertList = merchantCertInfoMapper.selectList(buildCertInfoWrapper(id, relationType));
        MerchantLicenseDO merchantAccessLicenseDO = merchantLicenseMapper.selectOne(buildLicenseWrapper(id, relationType));
        MerchantCardDO merchantAccessCardDO = merchantCardMapper.selectOne(buildCardWrapper(id, relationType));
        MerchantReportBusinessDO merchantAccessBusinessDO = merchantReportBusinessMapper.selectOne(buildBusinessWrapper(id));
        MerchantReportDto merchantAccessDto = new MerchantReportDto();
        merchantAccessDto.setMerchantReportInfo(merchantReportInfoDO);
        merchantAccessDto.setMerchantReportLicense(merchantAccessLicenseDO);
        merchantAccessDto.setMerchantReportCard(merchantAccessCardDO);
        merchantAccessDto.setMerchantReportBusiness(merchantAccessBusinessDO);
        if (CollectionUtils.isEmpty(merchantAccessCertList)) {
            return merchantAccessDto;
        }
        Map<Integer, List<MerchantCertInfoDO>> merchantAccessCertMap = merchantAccessCertList.stream()
                .collect(Collectors.groupingBy(merchantAccessCertInfoDO -> merchantAccessCertInfoDO.getType()));
        List<MerchantCertInfoDO> legalList = merchantAccessCertMap.get(MerchantEnum.CERT_INFO_TYPE.LEGAL.getCode());
        List<MerchantCertInfoDO> contactList = merchantAccessCertMap.get(MerchantEnum.CERT_INFO_TYPE.CONTACT.getCode());
        List<MerchantCertInfoDO> controllerList = merchantAccessCertMap.get(MerchantEnum.CERT_INFO_TYPE.CONTROLLER.getCode());
        List<MerchantCertInfoDO> benefitList = merchantAccessCertMap.get(MerchantEnum.CERT_INFO_TYPE.BENEFIT.getCode());
        List<MerchantCertInfoDO> shareholderList = merchantAccessCertMap.get(MerchantEnum.CERT_INFO_TYPE.SHAREHOLDER.getCode());
        if (CollectionUtils.isNotEmpty(legalList)) {
            merchantAccessDto.setMerchantReportLegal(legalList.get(0));
        }
        if (CollectionUtils.isNotEmpty(contactList)) {
            merchantAccessDto.setMerchantReportContact(contactList.get(0));
        }
        if (CollectionUtils.isNotEmpty(controllerList)) {
            merchantAccessDto.setMerchantReportController(controllerList.get(0));
        }
        if (CollectionUtils.isNotEmpty(benefitList)) {
            merchantAccessDto.setMerchantReportBenefitList(benefitList);
        }
        if (CollectionUtils.isNotEmpty(shareholderList)) {
            merchantAccessDto.setMerchantReportShareholderList(shareholderList);
        }
        return merchantAccessDto;
    }

    @Override
    public void updateStatus(Long id, MerchantEnum.REPORT_STATUS accessStatus, String remark) {
        MerchantReportInfoDO merchantAccessInfoDO = new MerchantReportInfoDO();
        merchantAccessInfoDO.setId(id);
        merchantAccessInfoDO.setStatus(accessStatus.getCode());
        merchantAccessInfoDO.setMessage(remark);
        merchantReportInfoMapper.updateById(merchantAccessInfoDO);
    }

    @Override
    public void delete(Long id) {
        merchantReportInfoMapper.deleteById(id);
    }

    @Override
    public MerchantReportInfoDO queryByRequestId(String requestId) {
        return merchantReportInfoMapper.selectOne(MerchantReportInfoDO::getRequestId, requestId);
    }

    @Override
    public void updateReportInfo(MerchantReportInfoDO updateAccessInfoDO) {
        merchantReportInfoMapper.updateById(updateAccessInfoDO);
    }

    @Override
    public MerchantReportInfoDO queryByExtendB(String acctId, String channelCode) {
        return merchantReportInfoMapper.selectOne(MerchantReportInfoDO::getVirtualAccountNo, acctId, MerchantReportInfoDO::getChannelCode, channelCode);
    }

    @Override
    public MerchantReportInfoDO queryByMchRequestId(String sn, String mchRequestId) {
        return merchantReportInfoMapper.selectOne(MerchantReportInfoDO::getMchRequestId, mchRequestId,MerchantReportInfoDO::getSn,sn);
    }

    @Override
    public MerchantReportInfoDO detailByUserId(String userId) {
        return merchantReportInfoMapper.selectOne(MerchantReportInfoDO::getUserId,userId);
    }


    /**
     * 查询条件封装
     *
     * @param merchantReportInfoPageQueryDto
     * @return
     */
    QueryWrapper<MerchantReportInfoDO> buildInfoWrapper(MerchantReportInfoPageQueryDto merchantReportInfoPageQueryDto) {
        filterSn(merchantReportInfoPageQueryDto);
        QueryWrapperX<MerchantReportInfoDO> queryWrapper = new QueryWrapperX<>();
        queryWrapper.eq("a.delete_flag", CommonEnum.YES_NO_TYPE.NO.getCode());
        queryWrapper.likeIfPresent("a.sn", merchantReportInfoPageQueryDto.getLikeSn());
        queryWrapper.eqIfPresent("a.sn", merchantReportInfoPageQueryDto.getSn());
        queryWrapper.inIfPresent("a.sn", merchantReportInfoPageQueryDto.getSnList());
        queryWrapper.likeIfPresent("a.sub_mch_id", merchantReportInfoPageQueryDto.getSubMchId());
        queryWrapper.eqIfPresent("a.status", merchantReportInfoPageQueryDto.getStatus());
        queryWrapper.likeIfPresent("a.provider_code", merchantReportInfoPageQueryDto.getProviderCode());
        queryWrapper.likeIfPresent("a.name", merchantReportInfoPageQueryDto.getName());
        queryWrapper.likeIfPresent("bus.short_name", merchantReportInfoPageQueryDto.getShortName());
        queryWrapper.likeIfPresent("contact.name", merchantReportInfoPageQueryDto.getContactName());
        queryWrapper.likeIfPresent("a.user_id", merchantReportInfoPageQueryDto.getUserId());
        queryWrapper.likeIfPresent("contact.phone", merchantReportInfoPageQueryDto.getContactPhone());
        queryWrapper.likeIfPresent("a.request_id", merchantReportInfoPageQueryDto.getRequestId());
        queryWrapper.eqIfPresent("a.channel_code", merchantReportInfoPageQueryDto.getChannelCode());
        queryWrapper.geIfPresent("a.create_time", merchantReportInfoPageQueryDto.getStartQueryTime());
        queryWrapper.leIfPresent("a.create_time", merchantReportInfoPageQueryDto.getEndQueryTime());
        // queryWrapper.last(StringUtils.hasText(merchantReportInfoPageQueryDto.getAgentCode()),"info.agent_code
        // like %'"+merchantReportInfoPageQueryDto.getAgentCode()+"'%");
        queryWrapper.likeIfPresent("info.super_agent", merchantReportInfoPageQueryDto.getSuperAgent());
        return queryWrapper;
    }


    /**
     * 查询条件封装
     *
     * @param relationId
     * @param relationType
     * @return
     */
    LambdaQueryWrapper<MerchantCertInfoDO> buildCertInfoWrapper(Long relationId, Integer relationType) {
        LambdaQueryWrapperX<MerchantCertInfoDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantCertInfoDO::getRelationId, relationId);
        queryWrapper.eqIfPresent(MerchantCertInfoDO::getRelationType, relationType);
        return queryWrapper;
    }

    /**
     * 查询条件封装
     *
     * @param relationId
     * @param relationType
     * @return
     */
    LambdaQueryWrapper<MerchantLicenseDO> buildLicenseWrapper(Long relationId, Integer relationType) {
        LambdaQueryWrapperX<MerchantLicenseDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantLicenseDO::getRelationId, relationId);
        queryWrapper.eqIfPresent(MerchantLicenseDO::getRelationType, relationType);
        return queryWrapper;
    }

    /**
     * 查询条件封装
     *
     * @param relationId
     * @param relationType
     * @return
     */
    LambdaQueryWrapper<MerchantCardDO> buildCardWrapper(Long relationId, Integer relationType) {
        LambdaQueryWrapperX<MerchantCardDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantCardDO::getRelationId, relationId);
        queryWrapper.eqIfPresent(MerchantCardDO::getRelationType, relationType);
        return queryWrapper;
    }

    /**
     * 查询条件封装
     *
     * @param reportId
     * @return
     */
    LambdaQueryWrapper<MerchantReportBusinessDO> buildBusinessWrapper(Long reportId) {
        LambdaQueryWrapperX<MerchantReportBusinessDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantReportBusinessDO::getReportId, reportId);
        return queryWrapper;
    }


}
